#ifndef _PROCEDURE_H
#define _PROCEDURE_H
#include <pthread.h>
#include <semaphore.h>

#include <list>
#include <iostream>
#include "common.h"

typedef void (*read_param)(void * dataOut,void * dataIn);
typedef int (*act_func)(void * dataIn);
typedef int (*update_proc)(void * dataIn,void * stdData);
typedef void (*except_proc)(void);

typedef void (*query_func)(void * dataIn);

typedef struct
{
    /* data */
    read_param readParamFunc;
    act_func actFunc;
    update_proc updateFunc; 
    except_proc exceptFunc;
    query_func queryFunc;
    int queryInterval;
    int queryTimes;
    int runtime;
    int stage;
    int flag;
    eleActCheck * dataDesired;
}procNode;


typedef enum
{
   STAGE_NOT_START,
   STAGE_RUNNING,
   STAGE_QUERY,
   STAGE_END,
}en_stage;

#define MAX_PARAM_BUFF_LEN 1024

typedef enum
{
    PARAM_FOR_BASHZ,
    PARAM_FOR_DJCLEAN,
    PARAM_FOR_TRANSTUBE,
}en_paramInType;

class CProcedure
{
private:
    int m_eleId;
    int m_max_proc_num;
    int m_curr_proc_num;
    int m_exitFlag;  
    

    int m_moduleId;

    int m_paramInType;
    void * m_ptrParamIn;
    int m_deleteFlag;     
public:
    pthread_t procThreadHandle; 
    procNode * procNodeArrHead;    
    CProcedure();
    void setEleId(int idIn);

    void start(int moduleId);

    void exit(void);

    virtual ~CProcedure();

    int getExitFlag(void);
    void setExitFlag(int flagIn);

    int getCurrProcNum(void);
    void setCurrProcNum(int numIn);

    int getMaxProcNum(void);

    void configProc(procNode * ptrProcNodeHead,int numProcNode);

    void updateOneProc(void * dataIn);

    void setModuleId(int idIn);

    int getModuleId(void);

    int setParamIn(int paramType, void * paramIn);

    void * getParamIn(void);

    int getDelFlag(void);
    void setDelFlag(int flagIn);

    int read_param(void * dataOut);
};

class CProcedure_Dj:public CProcedure
{
private:
    int m_numHole;
    std::string m_movelineTrace;
    std::list<pos_dj> m_listPos; 
    int m_currPosNum;
    std::list<pos_dj>::iterator m_currIt;
    pos_dj m_refPos;//position of A1
    int m_deltaX;
    int m_deltaY;
public:
    int getNextPos(pos_dj * posOut);
    int setInitPos(pos_dj * posIn);
    int getNumPos(void);


    int getProcParam(int indexPos,int indexProc, void * paramOut);

    int setMoveTrace(char * buffIn, int len,void * paramIn);

    int setDelta(int deltaX, int deltaY);

    int start_dj(int moduleId);

    CProcedure_Dj();

    virtual ~CProcedure_Dj();

    void setCurrPosIndex(int posIndexIn);
};

void *procThread(void *);

void *procThread_dj(void *);
void *procThread_dynamicRead(void * paramIn);

#define MAX_OB_NUM 40

typedef std::list<CProcedure *> procList_T;

class ob_manage
{
private:
    procList_T ptrProcList[MAX_OB_NUM];//used for managing the data of each electl
    
    pthread_t m_moduleThreadHandle;
public:
    void attach(CProcedure * ptr,int obId);
    void dettach(CProcedure * ptr,int obId);

    void update(void * dataIn);

    ob_manage();
    ~ob_manage();

    void start(void);

    void checkRunningProcs(void);

    procList_T procListRunning;//used for managing procedure that is running
    
};

typedef struct _moduleProcParam
{
    //CUim_MainCtl * ptrUimCtl;
    //CRs485 * ptrRs485;
    //CCan * ptrSubBoardCtl;

}moduleProcParam;


void *moduleThread(void * param);

void set_for_openlid(ob_manage * pManagerIn);
void set_for_closelid(ob_manage * pManagerIn);
void set_for_xrAtoB(ob_manage * pManagerIn);
void set_for_bash(ob_manage * pManagerIn);
void set_for_trans(ob_manage * pManagerIn);
void set_for_bashmove(ob_manage * pManagerIn);
void set_for_dp8move(ob_manage * pManagerIn);

void set_for_dp8suck(ob_manage * pManagerIn);
void set_for_dp8droptip(ob_manage * pManagerIn);
void set_for_dp8spit(ob_manage * pManagerIn);
void set_for_dp8installtip(ob_manage * pManagerIn);

void set_for_xr(ob_manage * pManagerIn);
void set_for_bashz(ob_manage * pManagerIn, void * pstMoveParam);

void set_for_bashz1(ob_manage * pManagerIn, void * pstMoveParam);

void set_for_heat_seal(ob_manage * pManagerIn);

void set_for_dj(ob_manage * pManagerIn, void * actParam);

void set_for_djclean(ob_manage * pManagerIn, void * actParam);

void set_for_djreagent(ob_manage * pManagerIn, void * actParam);


void set_for_transtube(ob_manage * pManagerIn, void * actParam);

void set_for_dp8lld(void * actParam);
void set_for_dp8capsample(void * actParam);

extern sem_t sem_liquid_detect;

#endif